﻿module MoonRace.Physics


//-----------------------------------------------
// HelperMaths
let square x = x * x
    
//-----------------------------------------------
// Measurement conversions

[<Measure>]
type s

[<Measure>]
type m

[<Measure>]
type kg

[<Measure>]
type N = (kg m)/(s^2)


//-----------------------------------------------
// Vector... with a measure! omg
type Vector2<[<Measure>] 'a> (u:float<'a>, v:float<'a>) = 
    member this.U = u
    member this.V = v

    static member (~-) (v : Vector2<_>) =
        Vector2(-1.0 * v.U, -1.0 * v.V)

    static member (+) (v1:Vector2<_>, v2:Vector2<_>) =
        Vector2(v1.U + v2.U, v1.U + v2.V)

    static member (-) (v1:Vector2<_>, v2:Vector2<_>) =
        v1 + (-v2)

    static member (*) (v : Vector2<_>, a ) =
        Vector2(a * v.U, a * v.V)

    static member (*) (a, v: Vector2<_>) =
        v * a

    override this.ToString() =
        this.U.ToString() + " " + this.V.ToString()

//-----------------------------------------------
// Force equations

let ForceOf (mass:float<kg>) (acceleration:float<m/s^2>) = (mass * acceleration)
let AccelerationOf (force:float<N>) (mass:float<kg>) = force/mass

let ApplyAcceleration startV acceleration time : Vector2<m/s>= startV + (acceleration*time)
let ApplyVelocity startPoint velocity time = startPoint + (velocity*time)


//-----------------------------------------------
// Planets
type Planet = {mass:float<kg>; radius:float<m>}
let Earth = {mass = 5.97219e24<kg>; radius = 6371000.0<m>}
let Moon = {mass = 7.34767309e22<kg>; radius = 1737400.0<m>}

module Gravity = 
    let G = 6.67e-11<m ^ 3 / (kg s^2)>
    let F (mass1:float<kg>) (mass2:float<kg>) (radius:float<m>) = (G*mass1*mass2) / (square radius)

    let g planet = G * planet.mass / (square planet.radius)
    let gEarth = g Earth


